﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows.Input;
using System.ComponentModel;
using System.Linq;
using MachineQA.DataAccess;
using MachineQA.Properties;
using MachineQA.Model;

namespace MachineQA.ViewModel
{
    class LocationsViewModel : WorkspaceViewModel
    {
        readonly LocationRepository _locationRepository;
        LocationViewModel _selectedLocation;
        LocationViewModel _newLocation;
        ObservableCollection<LocationViewModel> _allLocations;

        public LocationsViewModel(LocationRepository locationRepository)
        {
            base.DisplayName = Resources.LocationsViewModel_DisplayName;
            _locationRepository = locationRepository;

            // Subscribe for notifications when new locations are added.
            _locationRepository.LocationAddedOrRemoved += this.OnLocationAddedToRepository;
            this.CreateAllLocations();
        }

        void CreateAllLocations()
        {
            List<LocationViewModel> all = (from loc in _locationRepository.GetLocations()
                                            select new LocationViewModel(loc, _locationRepository)).ToList();

            foreach (LocationViewModel lvm in all)
                lvm.PropertyChanged += this.OnLocationViewModelPropertyChanged;

            _allLocations = new ObservableCollection<LocationViewModel>(all);
            _allLocations.CollectionChanged += this.OnCollectionChanged;
        }

        #region Public Interface

        public ObservableCollection<LocationViewModel> AllLocations
        {
            get
            {
                // Get data fresh each time in case it changes
                List<LocationViewModel> all = (from loc in Constants.entities.Locations.ToList()    
                                               select new LocationViewModel(loc, _locationRepository)).ToList();
                _allLocations = new ObservableCollection<LocationViewModel>(all);
                return _allLocations;
            }
        }

        public LocationViewModel SelectedLocation
        {
            get
            {
                return _selectedLocation;
            }
            set
            {
                _selectedLocation = value;
            }
        }

        public LocationViewModel NewLocation
        {
            get
            {
                if (_newLocation == null)
                    _newLocation = new LocationViewModel(new Location(), _locationRepository);
                return _newLocation;
            }
            set
            {
                _newLocation = value;
            }
        }

        #endregion // Public Interface

        #region Base class overrides

        protected override void OnDispose()
        {
            foreach (LocationViewModel locationVM in this.AllLocations)
                locationVM.Dispose();

            this.AllLocations.Clear();

            // Unregister event handlers
            this.AllLocations.CollectionChanged -= this.OnCollectionChanged;
            _locationRepository.LocationAddedOrRemoved -= this.OnLocationAddedToRepository;
        }

        #endregion // Base class overrides 

        #region Event Handling

        void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null && e.NewItems.Count != 0)
                foreach (LocationViewModel locationVM in e.NewItems)
                    locationVM.PropertyChanged += this.OnLocationViewModelPropertyChanged;

            if (e.OldItems != null && e.OldItems.Count != 0)
                foreach (LocationViewModel locationVM in e.OldItems)
                    locationVM.PropertyChanged -= this.OnLocationViewModelPropertyChanged;
        }

        void OnLocationViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            string IsSelected = Resources.IsSelectedPropertyName;

            // Debugging only verification
            (sender as LocationViewModel).VerifyPropertyName(IsSelected);

            if (e.PropertyName == IsSelected)
            {
                this.OnPropertyChanged(Resources.IsSelectedPropertyName);
                _selectedLocation = _allLocations.Where((i) => i.IsSelected).First();
            }
        }

        void OnLocationAddedToRepository(object sender, LocationAddedOrRemovedEventArgs e)
        {
            var viewModel = new LocationViewModel(e.AffectedLocation, _locationRepository);
            this._allLocations.Add(viewModel);
        }

        #endregion // Event Handling

        RelayCommand _saveCommand;

        /// <summary>
        /// Returns a command that saves the machine.
        /// </summary>
        public ICommand SaveCommand
        {
            get
            {
                if (_saveCommand == null)
                {
                    _saveCommand = new RelayCommand(
                        param => this.Save(),
                        null
                        );
                }
                return _saveCommand;
            }
        }

        void Save()
        {
            _newLocation.Save();
            _newLocation = new LocationViewModel(new Location(), _locationRepository); // Prepare for another new item.
        }
    }
}
